package client

// 因为js无法跳过证书,所以在此进行一次转发

// api转发
import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
	"sync"
	"time"
)

// 全局的 HTTP 客户端和 Transport
var httpClient = &http.Client{
	Transport: &http.Transport{
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: true,
		},
		MaxIdleConns:        10,               // 连接池最大空闲连接数
		MaxIdleConnsPerHost: 10,               // 每个目标主机的最大空闲连接数
		IdleConnTimeout:     60 * time.Second, // 空闲连接超时时间
	},
}

// RequestOptions 定义请求选项
type RequestOptions struct {
	Method  string                 `json:"method"`  // 请求方法：GET 或 POST
	Port    string                 `json:"port"`    // 端口
	URL     string                 `json:"url"`     // 请求URL
	Params  map[string]interface{} `json:"params"`  // URL查询参数
	Body    map[string]interface{} `json:"body"`    // POST请求体
	Headers map[string]string      `json:"headers"` // 请求头
}

// 返回结果
type Result struct {
	Code int         `json:"code"` // 状态码
	Msg  string      `json:"msg"`  // 消息
	Data interface{} `json:"data"` // 数据
}

// 增加一个信号量来控制并发请求数量
var sem = make(chan struct{}, 5) // 最多允许 5 个并发请求

// 图片缓存
var imageCache = make(map[string][]byte)
var cacheMutex sync.Mutex

// FetchInsecure 处理不安全的HTTP请求
// 修改 FetchInsecure 函数以返回 Result 类型
func FetchInsecure(options RequestOptions) Result {
	// 等待信号量，控制并发请求数量
	sem <- struct{}{}
	defer func() { <-sem }()

	// 处理URL查询参数
	if len(options.Params) > 0 {
		query := url.Values{}
		for key, value := range options.Params {
			query.Add(key, fmt.Sprintf("%v", value))
		}
		if strings.Contains(options.URL, "?") {
			options.URL += "&" + query.Encode()
		} else {
			options.URL += "?" + query.Encode()
		}
	}

	var req *http.Request
	var err error

	// fmt.Printf("%s %s\n", options.Method, options.URL)
	// 根据请求方法创建请求
	if options.Method == "POST" {
		jsonBody, _ := json.Marshal(options.Body)
		req, err = http.NewRequest("POST", options.URL, bytes.NewBuffer(jsonBody))
		if err != nil {
			return Result{Code: 500, Msg: err.Error(), Data: nil}
		}
		for key, value := range options.Headers {
			req.Header.Set(key, value)
		}
	} else {
		req, err = http.NewRequest("GET", options.URL, nil)
		if err != nil {
			return Result{Code: 500, Msg: err.Error(), Data: nil}
		}
		for key, value := range options.Headers {
			req.Header.Set(key, value)
		}
	}

	// 发送请求
	resp, err := httpClient.Do(req)
	if err != nil {
		return Result{Code: 500, Msg: err.Error(), Data: nil}
	}
	// 确保响应体被关闭
	if resp != nil {
		defer resp.Body.Close()
	}

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return Result{Code: 500, Msg: err.Error(), Data: nil}
	}

	return Result{Code: resp.StatusCode, Msg: http.StatusText(resp.StatusCode), Data: string(body)}
}

// 修改 GetImage 函数以返回 Result 类型
func GetImage(options RequestOptions) Result {
	// 先检查缓存中是否已经存在该图片
	cacheMutex.Lock()
	if cachedImage, exists := imageCache[options.URL]; exists {
		cacheMutex.Unlock()
		return Result{Code: 200, Msg: "cached image success", Data: cachedImage}
	}
	cacheMutex.Unlock()

	// 等待信号量，控制并发请求数量
	sem <- struct{}{}
	defer func() { <-sem }()

	// 若缓存中不存在，发起请求获取图片
	req, err := http.NewRequest("GET", options.URL, nil)
	if err != nil {
		return Result{Code: 500, Msg: err.Error(), Data: nil}
	}
	for key, value := range options.Headers {
		req.Header.Set(key, value)
	}

	resp, err := httpClient.Do(req)
	if err != nil {
		return Result{Code: 500, Msg: err.Error(), Data: nil}
	}
	defer resp.Body.Close()

	// 检查响应状态码
	if resp.StatusCode != http.StatusOK {
		return Result{Code: resp.StatusCode, Msg: http.StatusText(resp.StatusCode), Data: nil}
	}

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return Result{Code: 500, Msg: err.Error(), Data: nil}
	}

	// 将图片数据存入缓存
	cacheMutex.Lock()
	imageCache[options.URL] = body
	cacheMutex.Unlock()

	return Result{Code: 200, Msg: "Success", Data: body}
}
